package com.crpc.core.loadBalance;

import com.crpc.common.crpcEnum.LoadBalancerEnums;
import com.crpc.core.config.ObjectWrapper;
import com.crpc.core.loadBalance.impl.ConsistentHashLoadBalance;
import com.crpc.core.loadBalance.impl.MinimumResponseLoadBalance;
import com.crpc.core.loadBalance.impl.RoundRobinLoadBalance;
import lombok.extern.slf4j.Slf4j;

import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

import static com.crpc.common.crpcEnum.LoadBalancerEnums.ROUND_ROBIN;

@Slf4j
public class LoadBalanceFactory {
    private static final ConcurrentHashMap<String, ObjectWrapper<LoadBalanceWrapper>> SERIALIZER_CACHE = new ConcurrentHashMap<>();
    private static final ConcurrentHashMap<Byte, ObjectWrapper<LoadBalanceWrapper>> SERIALIZER_CACHE_CODE = new ConcurrentHashMap<>();

    static {
        LoadBalanceWrapper RoundRobin = new LoadBalanceWrapper(ROUND_ROBIN.getCode(), ROUND_ROBIN.getType(), new RoundRobinLoadBalance());
        LoadBalanceWrapper ConsistentHash = new LoadBalanceWrapper(LoadBalancerEnums.ConsistentHash.getCode(), LoadBalancerEnums.ConsistentHash.getType(), new ConsistentHashLoadBalance());
        LoadBalanceWrapper MinimumResponse = new LoadBalanceWrapper(LoadBalancerEnums.MinimumResponse.getCode(), LoadBalancerEnums.MinimumResponse.getType(), new MinimumResponseLoadBalance());
        ObjectWrapper<LoadBalanceWrapper> roundRobinWrapper = new ObjectWrapper<>(ROUND_ROBIN.getCode(), ROUND_ROBIN.getType(), RoundRobin);
        ObjectWrapper<LoadBalanceWrapper> consistentHashWrapper = new ObjectWrapper<>(LoadBalancerEnums.ConsistentHash.getCode(), LoadBalancerEnums.ConsistentHash.getType(), ConsistentHash);
        ObjectWrapper<LoadBalanceWrapper> minimumResponseWrapper = new ObjectWrapper<>(LoadBalancerEnums.MinimumResponse.getCode(), LoadBalancerEnums.MinimumResponse.getType(), MinimumResponse);
        SERIALIZER_CACHE.put(ROUND_ROBIN.getType(), roundRobinWrapper);
        SERIALIZER_CACHE.put(LoadBalancerEnums.ConsistentHash.getType(), consistentHashWrapper);
        SERIALIZER_CACHE.put(LoadBalancerEnums.MinimumResponse.getType(), minimumResponseWrapper);
        SERIALIZER_CACHE_CODE.put(ROUND_ROBIN.getCode(), roundRobinWrapper);
        SERIALIZER_CACHE_CODE.put(LoadBalancerEnums.ConsistentHash.getCode(), consistentHashWrapper);
        SERIALIZER_CACHE_CODE.put(LoadBalancerEnums.MinimumResponse.getCode(), minimumResponseWrapper);
    }

    public static LoadBalanceWrapper getLoadBalance(String loadBalanceType) {
        ObjectWrapper<LoadBalanceWrapper> objectWrapper = SERIALIZER_CACHE.get(loadBalanceType);
        return objectWrapper != null ? objectWrapper.getObjectImpl() : SERIALIZER_CACHE.get(ROUND_ROBIN.getType()).getObjectImpl();
    }

    public static LoadBalanceWrapper getLoadBalance(byte loadBalanceCode) {
        ObjectWrapper<LoadBalanceWrapper> objectWrapper = SERIALIZER_CACHE_CODE.get(loadBalanceCode);
        return objectWrapper != null ? objectWrapper.getObjectImpl() : SERIALIZER_CACHE_CODE.get(ROUND_ROBIN.getCode()).getObjectImpl();
    }

    public static void addLoadBalanceList(List<ObjectWrapper<LoadBalance>> objectWrapper) {
        for (ObjectWrapper<LoadBalance> wrapper : objectWrapper) {
            ObjectWrapper<LoadBalanceWrapper> serializerWrapperObjectWrapper = new ObjectWrapper<>(wrapper.getObjectCode(), wrapper.getObjectType(), new LoadBalanceWrapper(wrapper.getObjectCode(), wrapper.getObjectType(), wrapper.getObjectImpl()));
            SERIALIZER_CACHE.put(wrapper.getObjectType(), serializerWrapperObjectWrapper);
            SERIALIZER_CACHE_CODE.put(wrapper.getObjectCode(), serializerWrapperObjectWrapper);
        }
    }
}
